# -*- coding: utf-8 -*-

__authur__ = 'Yu XH'


import numpy as np
import copy
import time

from myAI.hexmap.handle_map import *
from myAI.attdamage.handle_shoot import *

class Threat(object):
    def __init__(self, situation, myAgent):
        self.__color = myAgent.color
        self.__map_size = myAgent.get_map_size()
        n_hexes = self.__map_size['row'] * self.__map_size['col']
        self.our_oprs = copy.deepcopy(situation.our_oprs)
        self.observation = None  # 对myAgent中的observation作备份
        self.last_observation = myAgent.scenario_info[-1]
        self.basic_enemies = copy.deepcopy(situation.basic_enemies)
        self.dead_enemies = copy.deepcopy(situation.dead_enemies)
        self.enemy_bullets = copy.deepcopy(situation.enemy_bullets)
        self.__enemy_change_flag = False
        self.enemies = []
        self.enemies_copy = []
        self.init_enemies(situation.basic_enemies, myAgent)
            #  敌人信息：{dict}
            #  {
            #      "obj_id": 算子ID
            #      "operator": 算子属性
            #      "step": 发现算子的时刻
            #      "pos_probs": 位置概率
            #      "pos_update_step": 位置概率的更新时刻
            #      "pos_update_frequency": 位置概率的更新频率
            #      "remain_bullet_nums": 弹药剩余量
            #      "shoot_range": 算子对不同类型目标的射程
            #      "change_flag": 敌算子位置变化的标志
            #      "threat": 算子的威胁，格式同self.enemy_threat
            #  }
        self.__proximate_2_cities = self.calc_proximate_cities(myAgent)
        self.__max_spread_radius = {BopType.Vehicle: 5, BopType.Infantry: 3,
                                    BopType.Aircraft: 10}  # 限定敌方算子不可无限制扩散，此值给出了最大扩散半径
        self.enemy_threat = np.zeros((4, n_hexes), dtype=float)  # 敌方的威胁，[0]：对车辆 / [1]：对人员 / [2]：对大型空中目标 / [3]：对小型空中目标
        self.enemy_threat_copy = np.zeros((4, n_hexes), dtype=float)
        self.__last_step = -1
        # if self.__enemy_change_flag:
        #     self.update_enemy_threat()

    def update(self, situation, myAgent):
        while True:
            # 游戏结束时，线程退出
            if myAgent.observation is None:
                break
            # if myAgent.max_step - myAgent.observation['time']['cur_step'] <= 50:  # 最后50个step不更新威胁态势，从而保证在游戏结束前线程执行完毕
            #     break
            if myAgent.observation['time']['cur_step'] <= self.__last_step:
                time.sleep(0.05)
                continue
            # === 加锁 - in myAgent.observation ===
            myAgent.agenda.ipcArgs.mutex_observation.acquire()
            self.observation = copy.deepcopy(myAgent.observation)
            # === 释放 - in myAgent.observation ===
            myAgent.agenda.ipcArgs.mutex_observation.release()

            # ===加锁 - in situation===
            myAgent.agenda.ipcArgs.mutex_basic_situ.acquire()
            self.our_oprs = copy.deepcopy(situation.our_oprs_copy)
            self.basic_enemies = copy.deepcopy(situation.basic_enemies_copy)
            self.dead_enemies = copy.deepcopy(situation.dead_enemies_copy)
            self.enemy_bullets = copy.deepcopy(situation.enemy_bullets_copy)
            # ===释放 - in situation===
            myAgent.agenda.ipcArgs.mutex_basic_situ.release()

            self.__enemy_change_flag = False
            # begin_update_enemies = time.perf_counter()
            self.updateEnemies(self.basic_enemies, self.observation['time']['cur_step'], self.observation, myAgent)
            # print((f'\t|- updateEnemies: {time.perf_counter() - begin_update_enemies:.3f}s'))
            if self.__enemy_change_flag:
                self.update_enemy_threat()
            self.last_observation = copy.deepcopy(self.observation)
            self.__last_step = self.observation['time']['cur_step']
            # ===加锁 - out threat===
            myAgent.agenda.ipcArgs.mutex_threat_situ.acquire()
            self.enemies_copy = copy.deepcopy(self.enemies)
            self.enemy_threat_copy = copy.deepcopy(self.enemy_threat)
            # ===释放 - out threat===
            myAgent.agenda.ipcArgs.mutex_threat_situ.release()

    def init_enemies(self, enemies, myAgent):
        map_size = self.__map_size
        n_hex = map_size['row'] * map_size['col']
        cur_step = 0
        for enemy in enemies:
            enemy_info_first = {}
            enemy_info_first["obj_id"] = enemy['obj_id']
            enemy_info_first["operator"] = enemy
            enemy_info_first["step"] = cur_step
            enemy_info_first["pos_probs"] = np.zeros(n_hex, dtype=float)
            enemy_info_first["pos_update_step"] = cur_step
            enemy_info_first["pos_update_frequency"] = 200 / (enemy['basic_speed'] / 3.6)
            enemy_info_first["pos_probs"][mapid_2_matind(enemy['cur_hex'], map_size)] = 1.
            enemy_info_first["remain_bullet_nums"] = self.enemy_bullets[enemy['obj_id']]  # 敌算子弹药剩余量
            # -- 敌算子射程 ---
            enemy_info_first["shoot_range"] = {}
            enemy_info_first["shoot_range"][BopType.Vehicle] = \
                get_shoot_radius(enemy['carry_weapon_ids'], enemy_info_first["remain_bullet_nums"], BopType.Vehicle)
            enemy_info_first["shoot_range"][BopType.Infantry] = \
                get_shoot_radius(enemy['carry_weapon_ids'], enemy_info_first["remain_bullet_nums"],
                                 BopType.Infantry)
            enemy_info_first["shoot_range"][BopType.Aircraft] = \
                get_shoot_radius(enemy['carry_weapon_ids'], enemy_info_first["remain_bullet_nums"],
                                 BopType.Aircraft)
            # -----
            enemy_info_first["change_flag"] = False  # 敌算子位置变化的标志
            enemy_info_first["threat"] = np.zeros((4, n_hex))
            self.enemies.append(enemy_info_first)

    def updateEnemies(self, enemies, cur_step, observation, myAgent):
        map_size = self.__map_size
        n_hex = map_size['row'] * map_size['col']
        # 1.先更新观察到的敌方算子
        for enemy in enemies:
            enemy_info = self.get_enemy_info_by_id(enemy['obj_id'])
            if enemy_info:
                enemy_info["operator"] = enemy
                enemy_info["step"] = cur_step
                enemy_info["pos_probs"] = np.zeros(n_hex, dtype=float)
                enemy_info["pos_probs"][mapid_2_matind(enemy['cur_hex'], map_size)] = 1.
                enemy_info["pos_update_step"] = cur_step
                self.update_opr_threat(enemy_info, myAgent)
                self.__enemy_change_flag = True
            else:  # 首次观察到敌方算子
                enemy_info_first = {}
                enemy_info_first["obj_id"] = enemy['obj_id']
                enemy_info_first["operator"] = enemy
                enemy_info_first["step"] = cur_step
                enemy_info_first["pos_probs"] = np.zeros(n_hex, dtype=float)
                enemy_info_first["pos_update_step"] = cur_step
                enemy_info_first["pos_update_frequency"] = 200 / (enemy['basic_speed'] / 3.6)
                enemy_info_first["pos_probs"][mapid_2_matind(enemy['cur_hex'], map_size)] = 1.
                enemy_info_first["remain_bullet_nums"] = self.enemy_bullets[enemy['obj_id']]  # 敌算子弹药剩余量
                # -- 敌算子射程 ---
                enemy_info_first["shoot_range"] = {}
                enemy_info_first["shoot_range"][BopType.Vehicle] = \
                    get_shoot_radius(enemy['carry_weapon_ids'], enemy_info_first["remain_bullet_nums"], BopType.Vehicle)
                enemy_info_first["shoot_range"][BopType.Infantry] = \
                    get_shoot_radius(enemy['carry_weapon_ids'], enemy_info_first["remain_bullet_nums"],
                                     BopType.Infantry)
                enemy_info_first["shoot_range"][BopType.Aircraft] = \
                    get_shoot_radius(enemy['carry_weapon_ids'], enemy_info_first["remain_bullet_nums"],
                                     BopType.Aircraft)
                # -----
                enemy_info_first["change_flag"] = False  # 敌算子位置变化的标志
                enemy_info_first["threat"] = np.zeros((4, n_hex))
                self.update_opr_threat(enemy_info_first, myAgent)  # 更新敌算子的威胁等级
                self.__enemy_change_flag = True
                self.enemies.append(enemy_info_first)
        # 2.更新死亡的敌方算子
        if self.dead_enemies:
            for obj_id in self.dead_enemies:
                enemy_info = self.get_enemy_info_by_id(obj_id)
                if enemy_info:
                    self.enemies.remove(enemy_info)
                    self.__enemy_change_flag = True
        # 3.更新其它的敌方算子：不是当前时间更新的敌方算子
        our_changed_oprs = self.get_our_changed_oprs()
        for enemy_info in self.enemies:
            if enemy_info["step"] != cur_step:
                if self.check_update_pos_probs(enemy_info, cur_step):
                    # begin_update = time.perf_counter()
                    self.update_pos_probs(enemy_info, cur_step, observation, myAgent)
                    # print((f'\t\t|- update_pos_probs: {time.perf_counter() - begin_update:.3f}s'))
                    # begin_correct = time.perf_counter()
                    self.correct_pos_probs_visions(enemy_info, self.our_oprs, myAgent)
                    # print((f'\t\t|- correct_pos_probs_visions for enemies: {time.perf_counter() - begin_correct:.3f}s'))
                elif our_changed_oprs:  # 用我方位置变化的算子，修正敌方算子的位置
                    # begin_correct = time.perf_counter()
                    self.correct_pos_probs_visions(enemy_info, our_changed_oprs, myAgent)
                    # print((f'\t\t|- correct_pos_probs_visions for ours: {time.perf_counter() - begin_correct:.3f}s'))
                # if myAgent.observation['judge_info']:  # 利用裁决信息中的敌方射击行动，修正敌方算子的位置
                #     self.correct_pos_probs_judge_info(enemy_info, myAgent.observation['judge_info'], myAgent)
                if enemy_info['change_flag']:
                    # begin_update_threat = time.perf_counter()
                    self.update_opr_threat(enemy_info, myAgent)
                    # print((f'\t\t|- update_opr_threat: {time.perf_counter() - begin_update_threat:.3f}s'))
                    self.__enemy_change_flag = True

    def update_opr_threat(self, enemy_info, myAgent):
        """更新敌方某一个算子的威胁等级"""
        n_hexes = self.__map_size['row'] * self.__map_size['col']
        for m in range(4):  # 更新4类目标的威胁
            if m == ObservedType.Vehicle:
                tar_type = BopType.Vehicle
            elif m == ObservedType.Infantry:
                tar_type = BopType.Infantry
            else:
                tar_type = BopType.Aircraft
            # 确定敌方算子的位置
            enemy = enemy_info['operator']
            pos_probs = enemy_info['pos_probs']
            remain_bullet_nums = enemy_info["remain_bullet_nums"]
            # 确定可威胁的目标区域
            threat_radius = enemy_info["shoot_range"][tar_type]
            if threat_radius == 0:
                enemy_info['threat'][m] = np.zeros(n_hexes)
            else:
                dist_matrix = myAgent.my_map['dist_matrix']
                att_area = np.arange(n_hexes)[pos_probs > 0]
                tar_area = np.arange(n_hexes)[np.any(dist_matrix[att_area] <= threat_radius, axis=0)]
                threat_levels = calc_threat_levels(myAgent, enemy['carry_weapon_ids'],
                                                   remain_bullet_nums, pos_probs, tar_type,
                                                   tar_locs=tar_area, att_obj_type=enemy['type'],
                                                   att_blood=enemy['blood'], special_shoot=None)
                enemy_info['threat'][m] = np.zeros(n_hexes)
                enemy_info['threat'][m][tar_area] = threat_levels
        enemy_info['change_flag'] = False

    def calc_proximate_cities(self, myAgent):
        map_size = myAgent.get_map_size()
        n_hex = map_size['row'] * map_size['col']
        city_locs = np.array([city['coord'] for city in myAgent.scenario_info[-1]['cities']])
        city_loc_inds = mapid_2_matind(city_locs, map_size)
        dist_matrix = myAgent.my_map['dist_matrix']
        city_dist_matrix = dist_matrix[city_loc_inds]
        city_dist_matrix[city_dist_matrix > 20] = 20
        city_dist_matrix[city_dist_matrix < 3] = 3
        min_dist = np.min(city_dist_matrix, axis=0)
        if np.max(min_dist) == np.min(min_dist):
            min_dist_norm = np.ones(n_hex)
        else:
            min_dist_norm = (np.max(min_dist) - min_dist) / (np.max(min_dist) - np.min(min_dist))
        return min_dist_norm

    def get_our_changed_oprs(self):
        """输出位置发生变化的我方算子"""
        changed_oprs = []
        for opr in self.our_oprs:
            last_opr = self.get_last_bop(opr['obj_id'])
            if not last_opr:
                if last_opr['cur_hex'] != opr['cur_hex']:
                    changed_oprs.append(opr)
        return changed_oprs

    def check_update_pos_probs(self, enemy_info, cur_step):
        """ 更新敌方算子的位置概率的判断"""
        discover_step = enemy_info['step']
        last_update_step = enemy_info['pos_update_step']
        update_frequency = enemy_info['pos_update_frequency']
        # 判断是否需要更新
        updated_count = (last_update_step - discover_step) // update_frequency  # 已更新次数
        curr_cycle = (cur_step - discover_step) // update_frequency  # 当前处于的更新周期
        if curr_cycle > updated_count:  # 需要更新的依据
            return True
        return False

    def update_pos_probs(self, enemy_info, cur_step, observation, myAgent):
        """ 更新敌方算子的位置概率"""
        enemy = enemy_info['operator']
        dist_matrix = myAgent.my_map['dist_matrix']
        if enemy['type'] == BopType.Vehicle:
            cost_matrix = myAgent.my_map['cost_matrix'][0] / 20
        elif enemy['type'] == BopType.Infantry:
            cost_matrix = myAgent.my_map['cost_matrix'][1] / 144
        else:
            cost_matrix = dist_matrix
        pos_probs = enemy_info['pos_probs']
        map_size = self.__map_size
        n_hex = map_size['row'] * map_size['col']
        cur_hex = enemy['cur_hex']
        cur_hex_ind = mapid_2_matind(cur_hex, self.__map_size)
        # 夺控点
        city_locs = np.array([city['coord'] for city in observation['cities']])
        city_loc_inds = mapid_2_matind(city_locs, map_size)
        # 算子位置
        pos_locs = np.arange(n_hex)[pos_probs > 0]
        pos_size = pos_locs.size
        # 更新enemy_info['pos_update_step']
        enemy_info['pos_update_step'] = cur_step
        # 设定的最大扩散区域
        max_spread_radius = self.__max_spread_radius[enemy['type']]
        spread_area = np.arange(n_hex)[dist_matrix[cur_hex_ind] <= max_spread_radius]
        # spread_area_size = spread_area.size
        neighbor_matrix_full = (dist_matrix[pos_locs] <= 1)
        neighbor_matrix_full[np.arange(pos_size), pos_locs] = False
        neighbor_matrix = neighbor_matrix_full[:, spread_area]
        # 计算对夺控点的最大攻击等级
        att_level_2_dist = np.zeros(map_size['row'] + map_size['col'], dtype=float)
        att_level_2_dist[:21] = np.maximum(
            np.maximum(
                integrate_att_level(enemy['carry_weapon_ids'], self.enemy_bullets[enemy['obj_id']],
                                    BopType.Infantry)[enemy['blood'] - 1],
                integrate_att_level(enemy['carry_weapon_ids'], self.enemy_bullets[enemy['obj_id']], BopType.Vehicle)
            ),
            integrate_att_level(enemy['carry_weapon_ids'], self.enemy_bullets[enemy['obj_id']], BopType.Aircraft)
        )  # 21维向量，最大距离20，大于20的距离，攻击等级=0
        max_a_l = np.max(att_level_2_dist)
        # att_level_2_dist = np.concatenate((att_level_2_dist, np.zeros(map_size['row'] + map_size['col'])))
        if abs(max_a_l - 0) < 1e-8:
            max_att_levels_norm = np.ones(pos_size)
        else:
            max_att_levels_norm = np.max(
                att_level_2_dist[dist_matrix[city_loc_inds.reshape(-1, 1), pos_locs.reshape(1, -1)]],
                axis=0) / max_a_l  # 此值越大，向夺控点的靠近速率越小
        # 计算各六角格的静止参数
        lumbda = 2  # 指数参数
        stop_paras = np.maximum(max_att_levels_norm, self.__proximate_2_cities[pos_locs]) ** lumbda
        # 计算各六角格的原地静止概率
        min_stop_prob, max_stop_prob = 0.05, 0.8  # 分别以多大的概率停止在原地
        stop_probs = (max_stop_prob - min_stop_prob) * stop_paras + min_stop_prob
        stop_probs_matrix_full = np.zeros((pos_size, n_hex), dtype=float)
        stop_probs_matrix_full[np.arange(pos_size), pos_locs] = stop_probs
        stop_probs_matrix = stop_probs_matrix_full[:, spread_area]
        # 确定扩散中夺控点朝向性参数，=1时表示均匀向6个方向扩散
        max_orient_base = 2.  # 最大朝向夺控点的指数的底数
        orient_bases = (max_orient_base - 1) * stop_paras + 1
        # orient_base_matrix = np.tile(orient_bases.reshape(-1, 1), (1, n_hex))
        # 确定6个邻格的扩散概率
        cost_matrix_used = cost_matrix[pos_locs.reshape(-1, 1), spread_area.reshape(1, -1)]
        min_city_dist = np.min(cost_matrix[city_loc_inds.reshape(-1, 1), spread_area.reshape(1, -1)], axis=0)
        neighbor_dist = np.zeros(neighbor_matrix.shape, dtype=float)
        neighbor_dist[neighbor_matrix] = np.tile(min_city_dist, (pos_size, 1))[neighbor_matrix] + \
                                         cost_matrix_used[neighbor_matrix]
        neighbor_dist[np.logical_not(neighbor_matrix)] = np.nan
        max_neighbor_dist = np.nanmax(neighbor_dist, axis=1)
        neighbor_dist_rect = max_neighbor_dist.reshape(-1, 1) - neighbor_dist
        neighbor_powers = np.power(orient_bases.reshape(-1, 1), neighbor_dist_rect)
        neighbor_probs = neighbor_powers / np.nansum(neighbor_powers, axis=1).reshape(-1, 1)
        # 确定在所有格子上的扩散概率
        spread_probs = stop_probs_matrix + np.nan_to_num((1 - stop_probs).reshape(-1, 1) * neighbor_probs)
        # 根据扩散概率spread_probs，更新位置概率
        enemy_info['pos_probs'] = np.zeros(n_hex)
        enemy_info['pos_probs'][spread_area] = np.sum(pos_probs[pos_locs].reshape(-1, 1) * spread_probs, axis=0)
        enemy_info['change_flag'] = True

    def correct_pos_probs_visions(self, enemy_info, our_oprs, myAgent):
        """根据我方视野更新位置概率"""
        if not isinstance(our_oprs, list):
            our_oprs = [our_oprs]
        map_size = self.__map_size
        n_hexes = map_size['row'] * map_size['col']
        dist_matrix = myAgent.my_map['dist_matrix']
        terrain_vec = myAgent.my_map['terrain_vec']
        pos_probs = copy.deepcopy(enemy_info['pos_probs'])
        pos_locs = np.arange(n_hexes)[pos_probs > 0]
        n_pos_locs = pos_locs.size
        enemy = enemy_info['operator']
        # 确定敌方算子的被观察类型
        if enemy['type'] == BopType.Vehicle:
            observed_type = ObservedType.Large
        elif enemy['type'] == BopType.Infantry:
            observed_type = ObservedType.Medium
        elif enemy['sub_type'] == BopType.Helicopter:
            observed_type = ObservedType.Large
        else:
            observed_type = ObservedType.Little
        n_oprs = len(our_oprs)
        vision_radius_vec = np.zeros(n_oprs)
        opr_locs = np.zeros(n_oprs, dtype=int)
        see_matrix = np.zeros((n_oprs, n_pos_locs), dtype=bool)
        for m in range(n_oprs):
            opr = our_oprs[m]
            # 确定视野半径
            vision_radius_vec[m] = opr['observe_distance'][observed_type]
            opr_locs[m] = mapid_2_matind(opr['cur_hex'], map_size)
            if opr['type'] == BopType.Aircraft and enemy['type'] == BopType.Aircraft:
                see_matrix[m, :] = myAgent.my_map['see_matrix'][1][opr_locs[m], pos_locs.reshape(1, -1)]
            elif opr['type'] != BopType.Aircraft and enemy['type'] != BopType.Aircraft:
                see_matrix[m, :] = myAgent.my_map['see_matrix'][0][opr_locs[m], pos_locs.reshape(1, -1)]
            else:
                see_matrix[m, :] = myAgent.my_map['see_matrix'][2][opr_locs[m], pos_locs.reshape(1, -1)]
        dist_matrix_used = dist_matrix[opr_locs.reshape(-1, 1), pos_locs.reshape(1, -1)]
        in_vision_range = (dist_matrix_used <= vision_radius_vec.reshape(-1, 1))  # 有效距离范围的确定
        handle_area = in_vision_range & see_matrix  # 有效距离范围中，可视部分的确定
        rect_probs = np.ones(handle_area.shape, dtype=float)
        rect_probs[handle_area] = 0.2
        good_terrains = (terrain_vec[pos_locs] == TerrainType.Forest) | (terrain_vec[pos_locs] == TerrainType.Resident)
        terrain_rects = np.ones(pos_locs.size, dtype=float)
        terrain_rects[good_terrains] = terrain_rects[good_terrains] * 0.5
        safe_dists = np.outer(vision_radius_vec / 2., terrain_rects)
        see_bool = (dist_matrix_used <= safe_dists)
        rect_probs[see_bool] = 0.
        rect_probs_vec = np.min(rect_probs, axis=0)
        rect_probs_full = np.ones(n_hexes, dtype=float)
        rect_probs_full[pos_locs] = rect_probs_vec
        pos_probs = pos_probs * rect_probs_full
        if np.max(pos_probs) < 1e-8:
            enemy_loc = mapid_2_matind(enemy['cur_hex'], map_size)
            max_spread_radius = self.__max_spread_radius[enemy['type']]
            pos_probs = np.zeros(n_hexes, dtype=float)
            max_spread_bool = (dist_matrix[enemy_loc] <= max_spread_radius)
            pos_probs[max_spread_bool] = 1. / np.sum(max_spread_bool + 0)
        else:
            pos_probs = pos_probs / np.sum(pos_probs)
        if np.sum(np.abs(enemy_info['pos_probs'] - pos_probs)) > 1e-8:
            enemy_info['pos_probs'] = pos_probs
            enemy_info['change_flag'] = True

    def update_enemy_threat(self):
        """更新敌方的威胁态势"""
        n_hexes = self.__map_size['row'] * self.__map_size['col']
        self.enemy_threat = np.zeros((4, n_hexes))
        for enemy_info in self.enemies:
            for m in range(4):
                self.enemy_threat[m] += enemy_info['threat'][m]

    def get_enemy_info_by_id(self, obj_id):
        for enemyInfo in self.enemies:
            if enemyInfo['obj_id'] == obj_id:
                return enemyInfo
        return None

    def get_last_bop(self, obj_id):
        """
        Get bop in my last_observation based on its id.
        """
        for bop in self.last_observation['operators']:
            if obj_id == bop['obj_id']:
                return bop
        for bop in self.last_observation['passengers']:
            if obj_id == bop['obj_id']:
                return bop
        return None


    # def correct_pos_probs_judge_info(self, enemy_info,judge_info, myAgent):
    #     """根据敌方射击动作，进一步修正位置概率"""
    #     enemy = enemy_info['operator']
    #     pos_probs = copy.deepcopy(enemy_info['pos_probs'])
    #     map_size = self.__map_size
    #     n_hexes = map_size['row'] * map_size['col']
    #     # 根据敌方射击动作估计敌方位置
    #     for info in judge_info:
    #         if info['att_obj_id'] == enemy['obj_id']:
    #             # our_obj = myAgent.get_bop(info['target_obj_id'])
    #             our_obj = self.get_bop_lastobservation(info['target_obj_id'])
    #             our_loc_ind = mapid_2_matind(our_obj['cur_hex'], map_size)
    #             # 根据射击动作的距离和高差，进一步缩小敌方算子的位置区域
    #             possible_locs_bool = (myAgent.my_map['dist_matrix'][our_loc_ind] == info['distance'])
    #             elev_diff = myAgent.my_map['elev_diff_matrix'][our_loc_ind]
    #             elev_diff[elev_diff < 0] = 0
    #             elev_diff_level = elev_diff // 20
    #             possible_locs_bool = possible_locs_bool & (elev_diff_level == info['ele_diff'])
    #             shrunken_pos_probs = pos_probs[possible_locs_bool]
    #             sum_shrunken_pos_probs = np.sum(shrunken_pos_probs)
    #             if abs(sum_shrunken_pos_probs - 0) <= 1e-8:
    #                 n_possible_locs = np.sum(possible_locs_bool + 0)
    #                 if n_possible_locs != 0:
    #                     pos_probs = np.zeros(n_hexes, dtype=float)
    #                     pos_probs[possible_locs_bool] = 1. / n_possible_locs
    #             else:
    #                 pos_probs = np.zeros(n_hexes, dtype=float)
    #                 pos_probs[possible_locs_bool] = shrunken_pos_probs / sum_shrunken_pos_probs
    #     if np.sum(np.abs(enemy_info['pos_probs'] - pos_probs)) > 1e-8:
    #         enemy_info['pos_probs'] = pos_probs
    #         enemy_info['change_flag'] = True
